package com.mymail.dao;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;

import com.mymail.entity.User;
import com.mymail.test.SQLTest;

public abstract class DAOImp {
	public static final int INSERT_ERROR = -1;
	public static final int UNKNOW_ERROR = -3;
	private Connection con;
	private PreparedStatement stmt = null;
	private ResultSet result = null;
	
	protected boolean exeProcedure(String sql, Object[] objs){
		con = SQLTest.getConnect();
		CallableStatement stmt = null;
		try {
			stmt = con.prepareCall(sql);
			if (objs != null) {
				for (int i = 1; i <= objs.length; ++i) {
					stmt.setObject(i, objs[i-1]);
				}
			}
			stmt.execute();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (SQLException e) {
			} finally {
				SQLTest.close();
			}
		}
	}

	protected int exeProcedure1(String sql, Object[] objs) {
		con = SQLTest.getConnect();
		CallableStatement stmt = null;
		try {
			stmt = con.prepareCall(sql);
			stmt.registerOutParameter(1, Types.INTEGER);
			if (objs != null) {
				int j = 2;
				for (int i = 0; i < objs.length; ++i, ++j) {
					stmt.setObject(j, objs[i]);
				}
			}
			stmt.execute();
			return stmt.getInt(1);
		} catch (SQLException e) {
			e.printStackTrace();
			return UNKNOW_ERROR;
		} finally {
			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (SQLException e) {
			} finally {
				SQLTest.close();
			}

		}
	}

	protected int getCount(String sql, Object[] objs) {
		try {
			execute(sql, objs);
			result.last();
			return result.getRow();
		} catch (SQLException e) {
			e.printStackTrace();
			return -1;
		} finally {
			close();
		}
	}

	public int insert(String sql, Object[] objs) {
		try {
			setObjects(sql, objs);
			stmt.executeUpdate();
			// 这个stmt重用不怎么好，可以再得到一个Statement。
			result = stmt.executeQuery("SELECT LAST_INSERT_ID()");
			result.next();
			int newId = result.getInt(1);
			// System.out.println(newId);
			return newId;
		} catch (SQLException e) {
			e.printStackTrace();
			return INSERT_ERROR;
		} finally {
			close();
		}
	}

	private boolean execute(String sql, Object[] objs) throws SQLException {
		setObjects(sql, objs);
		if (stmt.execute()) {
			result = stmt.getResultSet();
			return true;
		} else {
			return false;
		}
	}

	protected boolean exe(String sql, Object[] objs) {
		try {
			execute(sql, objs);
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			close();
		}
	}

	protected boolean findOne(String sql, Object[] objs, Object obj) {
		try {
			if (execute(sql, objs)) {
				result.next();
				setAtribute(result, obj);
				return true;
			} else {
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			close();
		}
	}

	@SuppressWarnings("unchecked")
	protected ArrayList findArray(String sql, Object[] objs) {
		ArrayList arr = new ArrayList();
		try {
			if (execute(sql, objs)) {
				while (result.next())
					arr.add(getEntity(result));
			}
			return arr;
		} catch (SQLException e) {
			e.printStackTrace();
			return arr;
		} finally {
			close();
		}
	}

	private void setObjects(String sql, Object objs[]) throws SQLException {
		con = SQLTest.getConnect();
		stmt = con.prepareStatement(sql);
		if (objs != null) {
			for (int i = 0; i < objs.length; ++i) {
				stmt.setObject(i + 1, objs[i]);
			}
		}
	}

	private void close() {
		try {
			if (result != null) {
				result.close();
			}
			if (stmt != null) {
				stmt.close();
			}
		} catch (SQLException e) {
		} finally {
			result = null;
			stmt = null;
			SQLTest.close();
		}
	}

	protected abstract Object getEntity(ResultSet result) throws SQLException;

	protected abstract void setAtribute(ResultSet result, Object obj)
			throws SQLException;

}
